package fi.foyt.cs.persistence.dao.scene;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.Query;

import fi.foyt.cs.persistence.dao.GenericDAO;
import fi.foyt.cs.persistence.domainmodel.scene.SceneCategory;
import fi.foyt.cs.persistence.domainmodel.scene.SceneCategoryType;

public class SceneCategoryDAO extends GenericDAO<SceneCategory> {

  public SceneCategory create(String name, Long parentCategoryId, SceneCategoryType type, String externalId) {
    EntityManager entityManager = getEntityManager();

    entityManager.getTransaction().begin();
    try {
      SceneCategory category = new SceneCategory();
      category.setName(name);
      category.setExternalId(externalId);
      category.setType(type);
      category.setParentCategoryId(parentCategoryId);
      entityManager.persist(category);
      entityManager.getTransaction().commit();
      return category;
    } finally {
      if (entityManager.getTransaction().isActive())
        entityManager.getTransaction().rollback();
    }
  }

  public SceneCategory findByTypeAndExternalId(SceneCategoryType type, String externalId) {
    EntityManager entityManager = getEntityManager();
    Query query = entityManager.createQuery("select c from SceneCategory c where c.externalId = :externalId and c.type = :type");
    query.setParameter("externalId", externalId);
    query.setParameter("type", type);
    return getSingleResult(query);
  }

  @SuppressWarnings("unchecked")
  public List<SceneCategory> listAll() {
    EntityManager entityManager = getEntityManager();
    Query query = entityManager.createQuery("select c from SceneCategory c");
    return query.getResultList();
  }

  @SuppressWarnings("unchecked")
  public List<SceneCategory> listByType(SceneCategoryType type) {
    EntityManager entityManager = getEntityManager();
    Query query = entityManager.createQuery("select c from SceneCategory c where c.type = :type");
    query.setParameter("type", type);
    return query.getResultList();
  }

  @SuppressWarnings("unchecked")
  public List<SceneCategory> listByParentCategoryId(Long parentCategoryId) {
    EntityManager entityManager = getEntityManager();
    Query query;
    
    if (parentCategoryId != null) {
      query = entityManager.createQuery("select c from SceneCategory c where c.parentCategoryId = :parentCategoryId");
      query.setParameter("parentCategoryId", parentCategoryId);
    } else {
      query = entityManager.createQuery("select c from SceneCategory c where c.parentCategoryId is null");
    }
    
    return query.getResultList();
  }

  @SuppressWarnings("unchecked")
  public List<SceneCategory> listByParentCategoryId(Long parentCategoryId, int firstResult, int maxResults) {
    EntityManager entityManager = getEntityManager();
    Query query;
    
    if (parentCategoryId != null) {
      query = entityManager.createQuery("select c from SceneCategory c where c.parentCategoryId = :parentCategoryId");
      query.setParameter("parentCategoryId", parentCategoryId);
    } else {
      query = entityManager.createQuery("select c from SceneCategory c where c.parentCategoryId is null");
    }
    
    query.setFirstResult(firstResult);
    query.setMaxResults(maxResults);
    
    return query.getResultList();
  }
  
  public Integer countByParentCategoryId(Long parentCategoryId) {
    EntityManager entityManager = getEntityManager();
    Query query;
    
    if (parentCategoryId != null) {
      query = entityManager.createQuery("select count(c) from SceneCategory c where c.parentCategoryId = :parentCategoryId");
      query.setParameter("parentCategoryId", parentCategoryId);
    } else {
      query = entityManager.createQuery("select count(c) from SceneCategory c where c.parentCategoryId is null");
    }
    
    return (Integer) query.getSingleResult();
  }

  public SceneCategory updateName(SceneCategory sceneCategory, String name) {
    EntityManager entityManager = getEntityManager();

    entityManager.getTransaction().begin();
    try {
      sceneCategory.setName(name); 
      sceneCategory = entityManager.merge(sceneCategory);
      entityManager.getTransaction().commit();
      
      return sceneCategory;
    } finally {
      if (entityManager.getTransaction().isActive())
        entityManager.getTransaction().rollback();
    }
  }
}